package com.lbs.core.shared.parsing;


import java.util.ArrayList;
import java.util.List;

import com.lbs.core.shared.XmlRawInterface;
import com.lbs.core.shared.tables.AbstractData;

/**
 * Clase principal del parser de LizBet, contien una unidad de valor y esta clase define si la extrae del XML,
 * del AbstractData o es un simple string
 * 
 * @author asandoval
 *
 */

public class LbsBasicToken implements LbsTokenInterface {
	 XmlRawInterface xml;
	 AbstractData data;
	 String string;
	 
	 /**
	  * Constructor unico
	  * 
	  * 
	  * @param string El token
	  * @param xml El xml para extrar datos XML de el si fuera necesario
	  * @param data El AbstractData pa extraer datos de el si fuera necesario
	  */
	 
	 public LbsBasicToken(String string, XmlRawInterface xml, AbstractData data){
		 this.xml=xml;
		 this.data=data;
		 this.string=string;
	 }
	 
	 /**
	  * Devuelve el valor de string, ya sea el String como tal si no esta entre comillado,
	  *  o el valor de la referencia dentro del AbstractData o el XML
	  * 
	  * 
	  * @return El valor real
	  */
	 @Override
	 public Object getVal(){
	     //Es una resta de valores
		 if ((string.contains("-")) && (!string.startsWith("'"))) { 
	       System.out.println(string);
	       String[] resta = string.split("-");
	       Double left;
	       Double right;
	       
	       //Es un double??
	       try {
	    	 Double.parseDouble(resta[0]);
	         left = Double.valueOf(Double.parseDouble(resta[0]));
	       }
	       catch (Exception e){
	         LbsBasicToken token = new LbsBasicToken(resta[0], this.xml, this.data);
	         left = (Double)token.getVal();
	       }
	       
	       //Es un double???
	       try {
	    	 Double.parseDouble(resta[1]);
	         right = Double.valueOf(Double.parseDouble(resta[1]));
	       }
	       catch (Exception e){
	         LbsBasicToken token = new LbsBasicToken(resta[1], this.xml, this.data);
	         right = (Double)token.getVal();
	       }
	 
	       return Double.valueOf(left.doubleValue() - right.doubleValue()); 
	     }
	     Boolean isNumeric;
	     try{
	       Double.parseDouble(string);
	       isNumeric = Boolean.valueOf(true);
	     }
	     catch (Exception e){
	       isNumeric = Boolean.valueOf(false);
	     }
	 
	     if (isNumeric.booleanValue())
	       return Double.valueOf(Double.parseDouble(string));
	     if ((string.startsWith("\"")) || (string.startsWith("'")))
	       return string.replace("\"", "").replace("'", "");
	     if ((string.equals("true")) || (string.equals("false")))
	       return Boolean.valueOf(Boolean.parseBoolean(string));
	     if (string.equals("this"))
	       return this.data;
	     if (string.startsWith("xml:"))
	       return this.xml.get(string.substring(4));
	     if (string.startsWith("dat:"))
	       return (this.data.get(string.substring(4)) == null) || (this.data.get(string.substring(4)).equals("null")) ? "" : this.data.get(string.substring(4));
	     if (string.equals("null")) {
	       return null;
	     }
	     return this.data.get(string);
	 }
	 
	 
	   @Override
	public List<String> getFields() {
		     List<String> result = new ArrayList<String>();
		     Boolean isNumeric;
		     try {
		       Double.parseDouble(string);
		       isNumeric = Boolean.valueOf(true);
		     }
		     catch (Exception e){
		       isNumeric = Boolean.valueOf(false);
		     }
		 
		     if ((!string.trim().startsWith("'")) && (!string.equals("true")) && (!string.equals("false")) && (!isNumeric.booleanValue()) && (!string.equals("this"))) {
		       result.add(string.trim());
		     }
		     return result;
		   }

	   @Override
	   public String toString(){
		   return string + " = " + getVal();
	   }
}
